package com.invoice.analysis.ofd.util;

import com.invoice.analysis.entity.InvoiceEntity;
import com.invoice.analysis.ofd.service.EnumInvoiceType;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * @author 郑恩远
 * @version 1.0
 * @date 2024/11/6 17:00:38
 */
public class OFDUtil {

  public static void main(String[] args) {
    InvoiceEntity entity = analysis(
        new File("C:\\Users\\zhengenyuan\\Desktop\\ofd\\E9CA927530B45DE44547B7CFDE01346723C18B63D0CC7FD676EA54498E3318E2.ofd"));
    System.out.println(entity);
  }
  public static InvoiceEntity analysis(InputStream file) {
    ZipInputStream zipInputStream = new ZipInputStream(file);
    try {
      ZipEntry nextEntry;
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      NodeList tags = null;
      NodeList ofdNodes = null;
      NodeList contents = null;
      while ((nextEntry = zipInputStream.getNextEntry()) != null) {
        if ("Doc_0/Tags/CustomTag.xml".equalsIgnoreCase(nextEntry.getName())) {
          tags = getNodeList(zipInputStream, builder, "ofd:root");
        }
        if ("Doc_0/Pages/Page_0/Content.xml".equalsIgnoreCase(nextEntry.getName())) {
          contents = getNodeList(zipInputStream, builder, "ofd:TextObject");
        }
        if ("OFD.xml".equalsIgnoreCase(nextEntry.getName())) {
          ofdNodes = getNodeList(zipInputStream, builder, "ofd:CustomData");
        }
      }
      return analysis(tags, ofdNodes, contents);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  public static InvoiceEntity analysis(byte[] file) {
    ByteArrayInputStream bais = new ByteArrayInputStream(file);
    return analysis(bais);
  }

  private static NodeList getNodeList(ZipInputStream zipInputStream,DocumentBuilder builder, String name) throws IOException, SAXException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    Document document;
    byte[] buffer = new byte[2048];
    int len;
    while ((len = zipInputStream.read(buffer)) > 0) {
      bos.write(buffer, 0, len);
    }
    InputStream xmlStream = new ByteArrayInputStream(bos.toByteArray());
    document = builder.parse(xmlStream);
    return document.getElementsByTagName(name);
  }

  public static InvoiceEntity analysis(NodeList tags,  NodeList ofdNodes, NodeList contents) {
    InvoiceEntity invoiceEntity = new InvoiceEntity();
    if (contents == null) {
      return invoiceEntity;
    }
    HashMap<String, String> contentMap = new HashMap<>(contents.getLength());
    for (int i1 = 0; i1 < contents.getLength(); i1++) {
      Node contentNode = contents.item(i1);
      String id = contentNode.getAttributes().getNamedItem("ID").getTextContent();
      String value = contentNode.getTextContent();
      contentMap.put(id, value);
    }
    for (int i = 0; ofdNodes != null && i < ofdNodes.getLength(); i++) {
      Node item = ofdNodes.item(i);
      Node node = item.getFirstChild();
      String name = item.getAttributes().getNamedItem("Name").getNodeValue();
      String value = node.getTextContent();
      contentMap.put(name, value);
    }
    if (tags == null || tags.getLength() == 0) {
      for (String key : contentMap.keySet()) {
        EnumInvoiceType invoiceType = EnumInvoiceType.getValues().get(key);
        if (invoiceType == null) {
          continue;
        }
        invoiceType.idThreeVoid.accept(key, invoiceEntity, contentMap);
      }
      return invoiceEntity;
    }
    Node item = tags.item(0);
    NodeList childNodes = item.getChildNodes();
    extracted(childNodes, invoiceEntity, contentMap);
    return invoiceEntity;
  }
  public static InvoiceEntity analysis(File file) {
    try (ZipFile zipFile = new ZipFile(file)) {
      ZipEntry customTag = zipFile.getEntry("Doc_0/Tags/CustomTag.xml");
      ZipEntry content = zipFile.getEntry("Doc_0/Pages/Page_0/Content.xml");
      ZipEntry ofd = zipFile.getEntry("OFD.xml");
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      NodeList tags = customTag == null ? null : builder.parse(zipFile.getInputStream(customTag)).getElementsByTagName("ofd:root");
      NodeList ofdNodes = ofd == null ? null : builder.parse(zipFile.getInputStream(ofd)).getElementsByTagName("ofd:CustomData");
      NodeList contents = builder.parse(zipFile.getInputStream(content))
          .getElementsByTagName("ofd:TextObject");
      return analysis(tags, ofdNodes, contents);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  private static void extracted(
      NodeList childNodes, InvoiceEntity invoiceEntity, HashMap<String, String> contentMap) {
    for (int i = 0; i < childNodes.getLength(); i++) {
      Node node = childNodes.item(i);
      extracted(node.getChildNodes(), invoiceEntity, contentMap);
      String name = node.getNodeName();
      EnumInvoiceType invoiceType = EnumInvoiceType.getValues().get(name);
      if (invoiceType == null) {
        continue;
      }
      invoiceType.threeVoid.accept(node, invoiceEntity, contentMap);
    }
  }
}
